import anime from 'animejs/lib/anime.es.js';
import createVueApp from '../utils/createVueApp.js';
import { h } from 'vue';
import BubblingListItem from './BubblingListItem.vue';

function getKey(index) {
  return (Number(String(Math.random()).slice(2)) + Date.now() + (index || 0)).toString(36);
}

// const BubblingListItem = {
//   name: 'BubblingListItem',
//   render() {
//     return h('div', { class: 'bubbling-list-item', style: this.style }, this.$slots.default);
//   },
//   data() {
//     return {
//       style: {},
//     };
//   },
//   mounted() {
//     setTimeout(() => {
//       this.$emit('rendered');
//     }, 0);
//   },
// };

const BubblingList = {
  name: 'BubblingList',
  props: {
    keyField: { type: String, default: 'key' },
    dataSource: { type: Array, default: () => [] },
    itemStyle: { type: Object, default: () => ({}) },
    limitNumber: { type: Number, default: 5 },
    direction: {
      type: String,
      default: 'row',
      validator: (v) => ['row', 'column'].includes(v),
    },
    gutter: { type: [Number, String], default: 10 },
    autoplay: { type: Boolean, default: true },
    delay: { type: Number, default: 5 * 1000 },
  },
  data() {
    return {
      dataList: [],
    };
  },
  mounted() {
    this.$watch(
      () => this.dataSource,
      (dataSource) => {
        if (!dataSource || !dataSource.length) {
          return;
        }
        dataSource = dataSource.map((item, index) =>
          Object.assign({}, item, { [this.keyField]: item[this.keyField] || getKey(index) })
        );
        if (typeof this.limitNumber === 'number' && this.limitNumber > 0) {
          this.dataList = dataSource.slice(0, this.limitNumber);
          this.addProgressive(dataSource.slice(this.limitNumber), () => {
            if (this.autoplay === true) {
              this.addProgressive(this.dataSource, true);
            }
          });
        } else {
          this.dataList = dataSource.slice(0);
        }
      },
      { immediate: true }
    );
  },
  computed: {
    space() {
      let space = '0px';
      if (typeof this.gutter === 'number') {
        space = this.gutter / 2 + 'px';
      } else if (typeof this.gutter === 'string') {
        space = this.gutter.replace(/\d+/, ($0) => $0 / 2);
      }
      return {
        plus: space,
        minus: '-' + space,
      };
    },
  },
  methods: {
    add(data) {
      if (data) {
        if (!data[this.keyField]) {
          data[this.keyField] = getKey();
        }
        // this.dataList.unshift(data);
        this.createDom(data);
      }
    },
    del(data) {
      if (typeof data === 'number' && data > 0) {
        this.dataList.splice(data, 1);
      }
    },
    addProgressive(list, next) {
      let data = [].concat(list).filter(Boolean);
      if (data && data.length) {
        let iteration = (list, next) => {
          if (list && list.length) {
            this.add(list.splice(0, 1)[0]);
            setTimeout(() => {
              iteration(list, next);
            }, this.delay);
          } else if (next === true) {
            iteration(data.slice(0), next);
          } else if (typeof next === 'function') {
            iteration = null;
            data = null;
            return next();
          }
        };
        iteration(data.slice(0), next);
      }
    },
    createDom(data) {
      const container = this.$refs.container;
      if (container) {
        const style = Object.assign({}, this.itemStyle, {
          padding: this.space.plus,
        });
        const key = data[this.keyField];
        const slots = this.$slots.default(data);
        const rendered = () => this.del(this.limitNumber);
        const div = document.createElement('div');
        const vnode = createVueApp(BubblingListItem, { key: key, style: style, slots, on: { rendered } });
        vnode.$mount(div);
        const el = vnode.$el;
        if (container.firstElementChild) {
          container.insertBefore(el, container.firstElementChild);
        } else {
          container.appendChild(el);
        }
        const { clientWidth: width, clientHeight: height } = el;
        // console.log(width, height);
        el.style.width = 0;
        el.style.height = 0;
        anime({
          targets: el,
          width: { value: width, duration: 1000 },
          height: { value: height, duration: 1000 },
        });
      }
    },
  },
  render() {
    if (!this.dataList || !this.dataList.length) {
      return h(
        'div',
        {
          class: 'bubbling-list',
          style: {
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            width: '100%',
            height: '300px',
            overflow: 'hidden',
          },
        },
        this.$slots.empty || '暂无数据~'
      );
    }
    return h(
      'div',
      {
        class: 'bubbling-list',
        style: { width: '100%', height: '300px', overflow: 'hidden' },
      },
      [
        h(
          'div',
          {
            ref: 'container',
            class: 'bubbling-list-wrap',
            style: { display: 'flex', flexDirection: this.direction, margin: this.space.minus },
          },
          this.dataList.map((item) => {
            const style = Object.assign({}, this.itemStyle, {
              padding: this.space.plus,
            });
            return h(
              BubblingListItem,
              {
                style: style,
                on: { rendered: () => this.del(this.limitNumber) },
              },
              this.$slots.default(item)
            );
          })
        ),
      ]
    );
  },
};

BubblingList.install = function (vue) {
  vue.component(BubblingList.name, BubblingList);
};

export default BubblingList;
